package com.ttxs.tenant.datasource;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@Slf4j
@RequiredArgsConstructor
public class TenantAspect {
    private final TenantNameResolver tenantNameResolver;

    @Pointcut("@annotation(com.ttxs.tenant.datasource.TenantRoute) " +
            "|| @within(com.ttxs.tenant.datasource.TenantRoute)")
    public void tenantPointCut() {
    }

    @Around("tenantPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        if (isTenantRoute(point)) {
            TenantContextHolder.set(tenantNameResolver.resolve());
        }
        try {
            return point.proceed();
        } finally {
            TenantContextHolder.remove();
        }
    }

    private boolean isTenantRoute(ProceedingJoinPoint joinPoint) {
        Class<?> targetClass = joinPoint.getTarget().getClass();
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        return targetClass.isAnnotationPresent(TenantRoute.class) || method.isAnnotationPresent(TenantRoute.class);
    }
}
